{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "af01f399",
   "metadata": {},
   "source": [
    "# Python 类/对象\n",
    "\n",
    "Python 是一种面向对象的编程语言。\n",
    "\n",
    "Python 中的几乎所有东西都是一个对象，有它的属性和方法。\n",
    "\n",
    "类就像一个对象构造函数，或者是创建对象的“蓝图”。\n",
    "\n",
    "## 创建一个类\n",
    "要创建一个类，请使用关键字 class："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "24625d12",
   "metadata": {},
   "outputs": [],
   "source": [
    "class MyClass:\n",
    "  x = 5"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "551d4c85",
   "metadata": {},
   "source": [
    "## 创建对象\n",
    "现在我们可以使用名为 MyClass 的类来创建对象："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "f8d32feb",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "5\n"
     ]
    }
   ],
   "source": [
    "p1 = MyClass()\n",
    "print(p1.x)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "72914066",
   "metadata": {},
   "source": [
    "## __init__() 函数\n",
    "上面的例子是最简单形式的类和对象，在现实生活应用程序中并没有真正有用。\n",
    "\n",
    "要理解类的含义，我们必须了解内置的 __init__() 函数。\n",
    "\n",
    "所有类都有一个名为 __init__() 的函数，它总是在类被初始化时执行。\n",
    "\n",
    "使用 __init__() 函数为对象属性赋值，或在创建对象时需要执行的其他操作："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "02a84617",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "John\n",
      "36\n"
     ]
    }
   ],
   "source": [
    "class Person:\n",
    "  def __init__(self, name, age):\n",
    "    self.name = name\n",
    "    self.age = age\n",
    "\n",
    "p1 = Person(\"John\", 36)\n",
    "\n",
    "print(p1.name)\n",
    "print(p1.age)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "4c6214e4",
   "metadata": {},
   "source": [
    "## 对象方法\n",
    "对象也可以包含方法。 对象中的方法是属于该对象的函数。\n",
    "\n",
    "让我们在 Person 类中创建一个方法："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "3e7fb551",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Hello my name is John\n"
     ]
    }
   ],
   "source": [
    "class Person:\n",
    "  def __init__(self, name, age):\n",
    "    self.name = name\n",
    "    self.age = age\n",
    "\n",
    "  def myfunc(self):\n",
    "    print(\"Hello my name is \" + self.name)\n",
    "\n",
    "p1 = Person(\"John\", 36)\n",
    "p1.myfunc()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "75ae30f0",
   "metadata": {},
   "source": [
    "## self参数\n",
    "self 参数是对类当前实例的引用，用于访问属于该类的变量。\n",
    "\n",
    "它不必命名为 self ，您可以随意调用它，但它必须是类中任何函数的第一个参数："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "c8b19562",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Hello my name is John\n"
     ]
    }
   ],
   "source": [
    "class Person:\n",
    "  def __init__(mysillyobject, name, age):\n",
    "    mysillyobject.name = name\n",
    "    mysillyobject.age = age\n",
    "\n",
    "  def myfunc(abc):\n",
    "    print(\"Hello my name is \" + abc.name)\n",
    "\n",
    "p1 = Person(\"John\", 36)\n",
    "p1.myfunc()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "86a295f9",
   "metadata": {},
   "source": [
    "## 修改对象属性\n",
    "可以像这样修改对象的属性："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "1d9473ef",
   "metadata": {},
   "outputs": [],
   "source": [
    "p1.age = 40"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "4176dfee",
   "metadata": {},
   "source": [
    "## 删除对象属性\n",
    "使用 del 关键字删除对象的属性："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "44fdcf16",
   "metadata": {},
   "outputs": [
    {
     "ename": "AttributeError",
     "evalue": "age",
     "output_type": "error",
     "traceback": [
      "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[1;31mAttributeError\u001b[0m                            Traceback (most recent call last)",
      "\u001b[1;32m<ipython-input-9-4e24acd3d696>\u001b[0m in \u001b[0;36m<module>\u001b[1;34m\u001b[0m\n\u001b[1;32m----> 1\u001b[1;33m \u001b[1;32mdel\u001b[0m \u001b[0mp1\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mage\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m      2\u001b[0m \u001b[0mprint\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mp1\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mage\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n",
      "\u001b[1;31mAttributeError\u001b[0m: age"
     ]
    }
   ],
   "source": [
    "del p1.age\n",
    "print(p1.age)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "362395e6",
   "metadata": {},
   "source": [
    "## 删除对象\n",
    "使用 del 关键字删除对象："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "id": "ec7b55bb",
   "metadata": {},
   "outputs": [
    {
     "ename": "NameError",
     "evalue": "name 'p1' is not defined",
     "output_type": "error",
     "traceback": [
      "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[1;31mNameError\u001b[0m                                 Traceback (most recent call last)",
      "\u001b[1;32m<ipython-input-10-514dc63e5972>\u001b[0m in \u001b[0;36m<module>\u001b[1;34m\u001b[0m\n\u001b[0;32m      1\u001b[0m \u001b[1;32mdel\u001b[0m \u001b[0mp1\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m----> 2\u001b[1;33m \u001b[0mprint\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mp1\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m",
      "\u001b[1;31mNameError\u001b[0m: name 'p1' is not defined"
     ]
    }
   ],
   "source": [
    "del p1\n",
    "print(p1)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "aaebb92b",
   "metadata": {},
   "source": [
    "# Python 继承\n",
    "继承允许我们定义一个从另一个类继承所有方法和属性的类。\n",
    "\n",
    "父类是被继承的类，也称为基类。\n",
    "\n",
    "子类是从另一个类继承的类，也称为派生类。\n",
    "\n",
    "## 创建父类\n",
    "任何类都可以是父类，因此语法与创建任何其他类相同："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "e10d2a87",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "John Doe\n"
     ]
    }
   ],
   "source": [
    "class Person:\n",
    "  def __init__(self, fname, lname):\n",
    "    self.firstname = fname\n",
    "    self.lastname = lname\n",
    "\n",
    "  def printname(self):\n",
    "    print(self.firstname, self.lastname)\n",
    "\n",
    "#Use the Person class to create an object, and then execute the printname method:\n",
    "\n",
    "x = Person(\"John\", \"Doe\")\n",
    "x.printname()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "6cf3010b",
   "metadata": {},
   "source": [
    "## 创建子类\n",
    "要创建从另一个类继承功能的类，请在创建子类时将父类作为参数发送："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "id": "1f2a6ee4",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Mike Olsen\n"
     ]
    }
   ],
   "source": [
    "class Student(Person):\n",
    "  pass\n",
    "\n",
    "x = Student(\"Mike\", \"Olsen\")\n",
    "x.printname()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d61cedab",
   "metadata": {},
   "source": [
    "## 添加 __init__() 函数\n",
    "到目前为止，我们已经创建了一个继承父类的属性和方法的子类。\n",
    "\n",
    "我们想将 __init__() 函数添加到子类（而不是 pass 关键字）。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "id": "9b3ad997",
   "metadata": {},
   "outputs": [],
   "source": [
    "class Student(Person):\n",
    "  def __init__(self, fname, lname):\n",
    "    Person.__init__(self, fname, lname)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "id": "e4e1d75c",
   "metadata": {},
   "outputs": [],
   "source": [
    "class Student(Person):\n",
    "  def __init__(self, fname, lname):\n",
    "    super().__init__(fname, lname)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f74382b2",
   "metadata": {},
   "source": [
    "## 增加属性"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "id": "be748fbc",
   "metadata": {},
   "outputs": [],
   "source": [
    "class Student(Person):\n",
    "  def __init__(self, fname, lname, year):\n",
    "    super().__init__(fname, lname)\n",
    "    self.graduationyear = year\n",
    "\n",
    "x = Student(\"Mike\", \"Olsen\", 2019)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "ca8e9b06",
   "metadata": {},
   "source": [
    "## 增加方法"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "28d8b7f7",
   "metadata": {},
   "outputs": [],
   "source": [
    "class Student(Person):\n",
    "  def __init__(self, fname, lname, year):\n",
    "    super().__init__(fname, lname)\n",
    "    self.graduationyear = year\n",
    "\n",
    "  def welcome(self):\n",
    "    print(\"Welcome\", self.firstname, self.lastname, \"to the class of\", self.graduationyear)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "eb5a92af",
   "metadata": {},
   "source": [
    "# Python迭代器\n",
    "迭代器是一个包含可数个值的对象。\n",
    "\n",
    "迭代器是可以迭代的对象，这意味着您可以遍历所有值。\n",
    "\n",
    "从技术上讲，在 Python 中，迭代器是一个实现迭代器协议的对象，它由方法 __iter__() 和 __next__() 组成。\n",
    "## 创建迭代器\n",
    "要创建一个对象/类作为迭代器，必须实现方法 __iter__() 和 __next__() 。\n",
    "\n",
    "正如上面了解到的，所有类都有一个名为 __init__() 的函数，它允许在创建对象时进行一些初始化。\n",
    "\n",
    "__iter__() 方法的作用类似，可以进行操作（初始化等），但必须始终返回迭代器对象本身。\n",
    "\n",
    "__next__() 方法还允许执行操作，并且必须返回序列中的下一项。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "id": "7c7cdf2b",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1\n",
      "2\n",
      "3\n",
      "4\n",
      "5\n"
     ]
    }
   ],
   "source": [
    "class MyNumbers:\n",
    "  def __iter__(self):\n",
    "    self.a = 1\n",
    "    return self\n",
    "\n",
    "  def __next__(self):\n",
    "    x = self.a\n",
    "    self.a += 1\n",
    "    return x\n",
    "\n",
    "myclass = MyNumbers()\n",
    "myiter = iter(myclass)\n",
    "\n",
    "print(next(myiter))\n",
    "print(next(myiter))\n",
    "print(next(myiter))\n",
    "print(next(myiter))\n",
    "print(next(myiter))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a7c80d40",
   "metadata": {},
   "source": [
    "## 停止迭代\n",
    "如果有足够多的 next() 语句，或者如果它在 for 循环中使用，上面的例子将永远持续下去。\n",
    "\n",
    "为了防止迭代永远进行，我们可以使用 StopIteration 语句。\n",
    "\n",
    "在 __next__() 方法中，我们可以添加终止条件以在迭代完成指定次数时引发错误："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "id": "9b7dc943",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1\n",
      "2\n",
      "3\n",
      "4\n",
      "5\n",
      "6\n",
      "7\n",
      "8\n",
      "9\n",
      "10\n",
      "11\n",
      "12\n",
      "13\n",
      "14\n",
      "15\n",
      "16\n",
      "17\n",
      "18\n",
      "19\n",
      "20\n"
     ]
    }
   ],
   "source": [
    "class MyNumbers:\n",
    "  def __iter__(self):\n",
    "    self.a = 1\n",
    "    return self\n",
    "\n",
    "  def __next__(self):\n",
    "    if self.a <= 20:\n",
    "      x = self.a\n",
    "      self.a += 1\n",
    "      return x\n",
    "    else:\n",
    "      raise StopIteration\n",
    "\n",
    "myclass = MyNumbers()\n",
    "myiter = iter(myclass)\n",
    "\n",
    "for x in myiter:\n",
    "  print(x)"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.10"
  },
  "toc": {
   "base_numbering": 1,
   "nav_menu": {},
   "number_sections": true,
   "sideBar": true,
   "skip_h1_title": false,
   "title_cell": "Table of Contents",
   "title_sidebar": "Contents",
   "toc_cell": false,
   "toc_position": {},
   "toc_section_display": true,
   "toc_window_display": false
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
